#include "stdafx.h"
#include <MyControls/Property.h>
#include <MyControls/App.h>
#include <MyControls/Resource.h>

namespace My {

// EditableList

EditableList::EditableList()
{
}

EditableList::EditableList(Size count, EditableObject * pValue) :
	std::list<EditableObject *>(count, pValue)
{
}

void EditableList::Resize(Size s)
{
	resize(s);
}

String PropertyBase::GetHint(const EditableList &) const 
{ 
	return String(); 
}
	
bool PropertyBase::ReadOnly(const EditableList &) const
{
	return false;
}

bool PropertyBase::Visible(const EditableList &) const
{
	return true;
}

const PropertyMap * PropertyBase::GetSubProperties(const EditableList &) const
{
	return 0;
}

void PropertyBase::GetObjects(const EditableList & in, EditableList & out) const
{
	out.Resize(in.size());
	std::copy(in.begin(), in.end(), out.begin());
}

Widget * PropertyBase::CreateControl(const EditableList &)
{ 
	return 0; 
}
	
void PropertyBase::FreeControl(Widget *)
{ 
}

bool PropertyBase::DefaultExpanded() const
{ 
	return false; 
}

void PropertyBase::Deserialize(xml::const_node const & n, EditableObject & obj) const
{
	EditableList list(1, &obj);
	const PropertyMap * pSubProperties = GetSubProperties(list);
	if (pSubProperties)
		My::Deserialize(* pSubProperties, n, obj);
}

void PropertyBase::Serialize(xml::node const & n, const EditableObject & obj) const
{
	EditableList list(1, const_cast<EditableObject *>(&obj));
	const PropertyMap * pSubProperties = GetSubProperties(list);
	if (pSubProperties)
		My::Serialize(* pSubProperties, n, obj);
}

bool PropertyBase::Serializable(const EditableList & list) const
{
	PropertyMap const * map = GetSubProperties(list);
	if (!map)
		return false;
	PropertyMap::const_iterator it;
	for (it = map->begin(); it != map->end(); ++it) {
		if (it->second->Serializable(list))
			return true;
	}
	return false;
}

// EditableObject

void EditableObject::UpdateProperty(PropertyBase * p)
{
	if (p != 0)
		p->DispatchEvent(PropertyChange(* this, p));
	else {
		const PropertyMap & map = GetProperties();
		for (PropertyMap::const_iterator it = map.begin(); it != map.end(); ++it)
			it->second->DispatchEvent(PropertyChange(* this, it->second));
	}
}

// Property Map

void Deserialize(PropertyMap const & map, xml::const_node const & n, EditableObject & obj)
{
	xml::const_node_vector children;
	n.children(children, "property");
	xml::const_node_vector::const_iterator it;
	for (it = children.begin(); it != children.end(); ++it) {
		String name = (*it)["name"];
		PropertyMap::const_iterator prop = map.find(name);
		if (prop != map.end()) {
			prop->second->Deserialize(*it, obj);
		}
	}
}

void Serialize(PropertyMap const & map, xml::node const & n, const EditableObject & obj)
{
	EditableList list(1, const_cast<EditableObject *>(&obj));
	PropertyMap::const_iterator it;
	for (it = map.begin(); it != map.end(); ++it) {
		if (!it->second->Serializable(list))
			continue;
		xml::node c = n.create("property");
		c["name"] = it->first;
		it->second->Serialize(c, obj);
	}
}

// PropertyMapClassBase

PropertyMapClassBase::PropertyMapClassBase()
	: m_Init(false) 
{ 
}

PropertyMapClassBase & PropertyMapClassBase::Init()
{
	m_Init = true; 
	return * this; 
}
	
bool PropertyMapClassBase::Initialized() const
{ 
	return m_Init; 
}

InvalidPropertyValueError::InvalidPropertyValueError()
	: std::runtime_error(GetApp().LoadString(MY_INVALID_PROPERTY_VALUE))
{
}

} // My